package com.vote.www.core;

import com.vote.www.utils.LocalDateTime;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

@Intercepts({@Signature(type=Executor.class,method="query",args={ MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })})
public class PageInterceptor implements Interceptor {

  public Object intercept(Invocation invocation) throws Throwable {
	//http://duanhengbin.iteye.com/blog/1998017
    //当前环境 MappedStatement，BoundSql，及sql取得
   /* MappedStatement mappedStatement=(MappedStatement)invocation.getArgs()[0];    
    Object parameter = invocation.getArgs()[1]; 
    BoundSql boundSql = mappedStatement.getBoundSql(parameter); 
    String originalSql = boundSql.getSql().trim();
    Object parameterObject = boundSql.getParameterObject();

    //Page对象获取，“信使”到达拦截器！
//    Page page = searchPageWithXpath(boundSql.getParameterObject(),".","page","page");

//    if(page!=null ){
      //Page对象存在的场合，开始分页处理
      String countSql = getCountSql(originalSql);
      Connection connection=mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection()  ;          
      PreparedStatement countStmt = connection.prepareStatement(countSql);  
      BoundSql countBS = copyFromBoundSql(mappedStatement, boundSql, countSql);
      DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, countBS);
      parameterHandler.setParameters(countStmt);
      ResultSet rs = countStmt.executeQuery();
      int totpage=0;
      if (rs.next()) {  
        totpage = rs.getInt(1);  
      }
      rs.close();  
      countStmt.close();  
      connection.close();
      
      //分页计算
//      page.setTotalRecord(totpage);
      
      //对原始Sql追加limit
//      int offset = (page.getPageNo() - 1) * page.getPageSize();
      StringBuffer sb = new StringBuffer();
//      sb.append(originalSql).append(" limit ").append(offset).append(",").append(page.getPageSize());
      BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, sb.toString());
      MappedStatement newMs = copyFromMappedStatement(mappedStatement,new BoundSqlSqlSource(newBoundSql));  
      invocation.getArgs()[0]= newMs;  
//    }
    return invocation.proceed();*/
	  
		try {
			MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
			Object parameter = invocation.getArgs()[1];
			BoundSql boundSql = mappedStatement.getBoundSql(parameter);
			String originalSql = boundSql.getSql().trim();
			Object parameterObject = boundSql.getParameterObject();

			if (parameterObject instanceof Map) {
		
				@SuppressWarnings("unchecked")
                Map<String, Object> object = (Map<String, Object>) parameterObject;
				List<Object> listObj = new ArrayList<Object>();
				
				for(Entry<String, Object> mp:object.entrySet()){
					if(mp.getValue() instanceof List){
						listObj = (List<Object>) mp.getValue();
					}
				}
				String item="";
				int h=0;
				for (ParameterMapping mapping : boundSql.getParameterMappings()) {
						String[] strings= mapping.getProperty().split("\\.");
						if(strings.length==1){
							if(object.get(mapping.getProperty())==null){
								if(listObj.size()==0){
									originalSql = originalSql.replaceFirst("[?]", "''");
								}else{
									originalSql = originalSql.replaceFirst("[?]", "'" + listObj.get(h) + "'");
								}
								h++;
							}else{
								originalSql = originalSql.replaceFirst("[?]", "'" + object.get(mapping.getProperty()) + "'");
							}
							
						}else if(strings.length==2){
							if(!item.equals(strings[0])){
								item = strings[0];
								h++;
							}
							originalSql = originalSql.replaceFirst("[?]", "'" + ((Map<String, Object>)listObj.get(h-1)).get(strings[1]) + "'");
						}
				}
				
				
			} else if (parameterObject instanceof String) {
				String str = (String) parameterObject;
				originalSql = originalSql.replaceFirst("[?]", "'" + str + "'");
			}

			System.out.println(mappedStatement.getResource());
			System.out.println(mappedStatement.getId());
			System.out.println("==============================sql开始============================" + LocalDateTime.now());
			System.out.println(deleteCRLFOnce(originalSql));
			System.out.println("==============================sql结束============================" + LocalDateTime.now());
			if (parameterObject != null) {
				System.out.println(parameterObject.toString());
			}
		} catch (Exception e) {
			System.err.println("显示sql出错！");
//			e.printStackTrace();
		}
		return invocation.proceed();
	}
  
 

  /**
   * 复制MappedStatement对象
   */
 /* private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
    Builder builder = new Builder(ms.getConfiguration(),ms.getId(),newSqlSource,ms.getSqlCommandType());
    
    builder.resource(ms.getResource());
    builder.fetchSize(ms.getFetchSize());
    builder.statementType(ms.getStatementType());
    builder.keyGenerator(ms.getKeyGenerator());
    builder.keyProperty(ms.getKeyProperty());
    builder.timeout(ms.getTimeout());
    builder.parameterMap(ms.getParameterMap());
    builder.resultMaps(ms.getResultMaps());
    builder.resultSetType(ms.getResultSetType());
    builder.cache(ms.getCache());
    builder.flushCacheRequired(ms.isFlushCacheRequired());
    builder.useCache(ms.isUseCache());
    
    return builder.build();
  }*/

  /**
   * 复制BoundSql对象
   */
 /* private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
    BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
    for (ParameterMapping mapping : boundSql.getParameterMappings()) {
        String prop = mapping.getProperty();
        if (boundSql.hasAdditionalParameter(prop)) {
            newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
        }
    }
    return newBoundSql;
  }*/

  /**
   * 根据原Sql语句获取对应的查询总记录数的Sql语句
   */
  private String getCountSql(String sql) {
    return "SELECT COUNT(*) FROM (" + sql + ") aliasForPage";
  }

  public class BoundSqlSqlSource implements SqlSource {
      BoundSql boundSql;
      public BoundSqlSqlSource(BoundSql boundSql) {
        this.boundSql = boundSql;  
      }  
      public BoundSql getBoundSql(Object parameterObject) {
        return boundSql;  
      }  
    }  
  public Object plugin(Object arg0) {
     return Plugin.wrap(arg0, this);
  }
  public void setProperties(Properties arg0) {
  }
  private static String deleteCRLFOnce(String input) {
	    return input.replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1");  
  }  
}